summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_vulkan/present/fxaa.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_vulkan/present/fxaa.cpp')
-rw-r--r--src/video_core/renderer_vulkan/present/fxaa.cpp144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/video_core/renderer_vulkan/present/fxaa.cpp b/src/video_core/renderer_vulkan/present/fxaa.cpp
new file mode 100644
index 000000000..6f87ddebb
--- /dev/null
+++ b/src/video_core/renderer_vulkan/present/fxaa.cpp
@@ -0,0 +1,144 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/common_types.h"
+
+#include "video_core/host_shaders/fxaa_frag_spv.h"
+#include "video_core/host_shaders/fxaa_vert_spv.h"
+#include "video_core/renderer_vulkan/present/fxaa.h"
+#include "video_core/renderer_vulkan/present/util.h"
+#include "video_core/renderer_vulkan/vk_scheduler.h"
+#include "video_core/renderer_vulkan/vk_shader_util.h"
+#include "video_core/vulkan_common/vulkan_device.h"
+
+namespace Vulkan {
+
+FXAA::FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent)
+ : m_device(device), m_allocator(allocator), m_extent(extent),
+ m_image_count(static_cast<u32>(image_count)) {
+ CreateImages();
+ CreateRenderPasses();
+ CreateSampler();
+ CreateShaders();
+ CreateDescriptorPool();
+ CreateDescriptorSetLayouts();
+ CreateDescriptorSets();
+ CreatePipelineLayouts();
+ CreatePipelines();
+}
+
+FXAA::~FXAA() = default;
+
+void FXAA::CreateImages() {
+ for (u32 i = 0; i < m_image_count; i++) {
+ Image& image = m_dynamic_images.emplace_back();
+
+ image.image = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
+ image.image_view =
+ CreateWrappedImageView(m_device, image.image, VK_FORMAT_R16G16B16A16_SFLOAT);
+ }
+}
+
+void FXAA::CreateRenderPasses() {
+ m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
+
+ for (auto& image : m_dynamic_images) {
+ image.framebuffer =
+ CreateWrappedFramebuffer(m_device, m_renderpass, image.image_view, m_extent);
+ }
+}
+
+void FXAA::CreateSampler() {
+ m_sampler = CreateWrappedSampler(m_device);
+}
+
+void FXAA::CreateShaders() {
+ m_vertex_shader = CreateWrappedShaderModule(m_device, FXAA_VERT_SPV);
+ m_fragment_shader = CreateWrappedShaderModule(m_device, FXAA_FRAG_SPV);
+}
+
+void FXAA::CreateDescriptorPool() {
+ // 2 descriptors, 1 descriptor set per image
+ m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, m_image_count);
+}
+
+void FXAA::CreateDescriptorSetLayouts() {
+ m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, 2);
+}
+
+void FXAA::CreateDescriptorSets() {
+ VkDescriptorSetLayout layout = *m_descriptor_set_layout;
+
+ for (auto& images : m_dynamic_images) {
+ images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, {layout});
+ }
+}
+
+void FXAA::CreatePipelineLayouts() {
+ m_pipeline_layout = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layout);
+}
+
+void FXAA::CreatePipelines() {
+ m_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout,
+ std::tie(m_vertex_shader, m_fragment_shader));
+}
+
+void FXAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
+ Image& image = m_dynamic_images[image_index];
+ std::vector<VkDescriptorImageInfo> image_infos;
+ std::vector<VkWriteDescriptorSet> updates;
+ image_infos.reserve(2);
+
+ updates.push_back(
+ CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 0));
+ updates.push_back(
+ CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 1));
+
+ m_device.GetLogical().UpdateDescriptorSets(updates, {});
+}
+
+void FXAA::UploadImages(Scheduler& scheduler) {
+ if (m_images_ready) {
+ return;
+ }
+
+ scheduler.Record([&](vk::CommandBuffer cmdbuf) {
+ for (auto& image : m_dynamic_images) {
+ ClearColorImage(cmdbuf, *image.image);
+ }
+ });
+ scheduler.Finish();
+
+ m_images_ready = true;
+}
+
+VkImageView FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
+ VkImageView source_image_view) {
+ const Image& image{m_dynamic_images[image_index]};
+ const VkImage output_image{*image.image};
+ const VkDescriptorSet descriptor_set{image.descriptor_sets[0]};
+ const VkFramebuffer framebuffer{*image.framebuffer};
+ const VkRenderPass renderpass{*m_renderpass};
+ const VkPipeline pipeline{*m_pipeline};
+ const VkPipelineLayout layout{*m_pipeline_layout};
+ const VkExtent2D extent{m_extent};
+
+ UploadImages(scheduler);
+ UpdateDescriptorSets(source_image_view, image_index);
+
+ scheduler.RequestOutsideRenderPassOperationContext();
+ scheduler.Record([=](vk::CommandBuffer cmdbuf) {
+ TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL);
+ TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
+ BeginRenderPass(cmdbuf, renderpass, framebuffer, extent);
+ cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
+ cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, {});
+ cmdbuf.Draw(4, 1, 0, 0);
+ cmdbuf.EndRenderPass();
+ TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
+ });
+
+ return *image.image_view;
+}
+
+} // namespace Vulkan